#include "CDefender.h"
#include <QDesktopServices>
#include <QFileInfo>
#include <QDebug>
#include <QUrl>
#include <QCoreApplication>
#include <QProcess>

CDefender::CDefender(QObject *parent) : QObject(parent)
{

}

void CDefender::init()
{
    //读配置文件
    QString strIniFile = QCoreApplication::applicationDirPath() + "/AppDefender.ini";

    m_pSettings = new QSettings(strIniFile,QSettings::IniFormat,this);
    if(!QFile::exists(strIniFile)){
        qWarning()<<"配置文件不存在!";
    }
    int nCheckSpan = m_pSettings->value("Settings/CheckSpan",3).toInt();
    if(nCheckSpan < 1)
        nCheckSpan = 1;
    qInfo()<<"检查进程时间间隔为:"<<nCheckSpan<<"s";

    //读取应用列表
    int nSize = m_pSettings->beginReadArray("AppList");
    for (int i = 0; i < nSize; i++) {
        m_pSettings->setArrayIndex(i);
        this->append(m_pSettings->value("AppName").toString());
    }
    m_pSettings->endArray();

    //定时检查
    m_pTimer = new QTimer(this);
    connect(m_pTimer,&QTimer::timeout,this,&CDefender::slotCheckTime);

    if(!m_mapDefender.isEmpty()){
        m_pTimer->start(nCheckSpan * 1000);
        slotCheckTime();
    }

    //添加到系统托盘
    initSysTray();
}

void CDefender::append(QString strAppName)
{
    // "/tmp/archive.exe" baseName = "archive"
    QFileInfo appFileInfo(strAppName);
    QString strSimpleName = appFileInfo.fileName();
    //判断是有效的可执行文件
    if(!strAppName.isEmpty() && (appFileInfo.suffix() == "exe"))
    {
        m_mapDefender.insert(strSimpleName,strAppName);
        qDebug()<<"添加需要守护的进程:"<<strSimpleName<<strAppName;
    }else{
        qWarning()<<"无法守护！非可守护进程:"<<strAppName;
    }
}

void CDefender::remove(QString strAppName)
{
    m_mapDefender.remove(QFileInfo(strAppName).baseName());
}

bool CDefender::isRuning(QString strName)
{
    /*说明:判断进程是否已经存在运行实例 依赖WindowsAPI*/
    int i = 0;
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(pe32);
    HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if(hProcessSnap == INVALID_HANDLE_VALUE)
    {
        i += 0;
    }
    bool bMore = ::Process32First(hProcessSnap, &pe32);
    while(bMore)
    {
        QString strProcessName = QString::fromWCharArray(pe32.szExeFile);
        if(strProcessName == strName)
        {
            i++;
        }
        bMore = ::Process32Next(hProcessSnap, &pe32);
    }

    return (i > 0) ? true : false; //大于0
}

void CDefender::slotCheckTime()
{
    //检查守护的进程是否正常运行
    foreach(QString strSimpleName,m_mapDefender.keys()){
        if(!isRuning(strSimpleName)){
            QString strFileName = m_mapDefender.value(strSimpleName);
            bool bSuccess = openUrl(strFileName);
            qInfo()<<"启动:"<<strFileName<<" "<<(bSuccess ? "成功" : "失败");
        }else{
            qDebug()<<"检查："<<strSimpleName;
        }
    }
}

bool CDefender::openUrl(QString strUrl)
{
    QUrl url = QUrl(QString("file:///%1").arg(strUrl),QUrl::TolerantMode);

    //@NOTE 注意！！！
    //QCoreApplication 应用打开其他文件会失败  此功能需要QApplication才行
    return  QDesktopServices::openUrl(url);
}

void CDefender::initSysTray()
{
    QMenu *menuTray = new QMenu;
    QAction *actQuit = new QAction(tr("退出"), menuTray);
    menuTray->addAction(actQuit);

    QSystemTrayIcon *sysTrayIcon = new QSystemTrayIcon(this);
    sysTrayIcon->setIcon(QIcon(":/AppDefender.ico"));//设置托盘图标的icon
    sysTrayIcon->show();//展示系统托盘图片
    sysTrayIcon->setContextMenu(menuTray);
    sysTrayIcon->setToolTip(tr("应用守护精灵V1.0\n可通过配置文件配置守护列表"));
    sysTrayIcon->showMessage(tr("应用守护精灵V1.0"), tr("应用守护已启动"), QSystemTrayIcon::Information, 3000);

    connect(sysTrayIcon, &QSystemTrayIcon::activated,this, [=]{
        menuTray->exec();
    });
    connect(actQuit, SIGNAL(triggered()), qApp, SLOT(quit()));
}

